package org.raymond.iworks.study.basic.thread.completablefuture;

import cn.hutool.core.thread.ThreadUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

@Slf4j
public class Demo1 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        test0();
    }


    public static void test0() throws ExecutionException, InterruptedException {
        ThreadPoolExecutor te = new ThreadPoolExecutor(1, 1, 0, TimeUnit.MICROSECONDS, new LinkedBlockingQueue<>());
        CompletableFuture<Void> future = CompletableFuture.runAsync(()->{
            log.info("hello world");
        }, te);
        future.get();
        te.shutdown(); // 使用自定义线程池需要主动关闭线程池
        log.info("end");
    }
    public static void test1(){
        // ForkJoin的线程池来执行被提交的任务
        CompletableFuture<String> future = CompletableFuture.supplyAsync(()->{
            log.info("compute test");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "test";
        });
        // 通过get或join获取最终返回结果
        String result = future.join();
        log.info("get result: " + result);
    }

    public static void test2(){
        // 先执行第一个任务
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(()->{
            log.info("compute 1");
            // 执行完毕后，返回一个值
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 1;
        });
        // 传入第一个任务的执行结果(第一个任务必须执行完毕)，执行第二个任务
        // thenApply(有返回值，有入参) / thenAccept(无返回值，有入参) / thenRun(无返回值，无入参)
        CompletableFuture<Integer> future2 = future1.thenApply((p)->{
            log.info("compute 2");
            // 执行完毕后，返回两个执行结果之和
            return p+10;
        });
        log.info("result: " + future2.join());
    }

    public static void test3(){
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(()->{
            log.info("compute 1");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 1;
        });
        // 任务1组合任务2
        CompletableFuture<Integer> future2 = future1.thenCompose((r)->{
            log.info("compose 2");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            CompletableFuture<Integer> future3 = CompletableFuture.supplyAsync(()->{
                log.info("compute 3");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return r+10;
            });
            log.info("after compose 2");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return future3;
        });

        log.info("{}", future2.join());
    }
}
